#ifndef UNITTESTER_H_JM_20130111
#define UNITTESTER_H_JM_20130111

// ## jmlib
#include "UnitTest.h"
// ## c++
#include <vector>
#include <iostream>
#include <string>

namespace jmlib {

	class  UnitTester {
	public:
		struct FirstTestFailException { };

		static UnitTester* getInstance();

		virtual ~UnitTester();

		void registerTest(UnitTest* t);
		virtual void runTests();

		void setOutput(std::ostream& outputStream) {
			outputStream_ = outputStream_;
		}

		std::ostream& getOutput() { return *outputStream_; }

		void setFirstTestFailStopTesting(bool stop) { 
			firstTestFailStopTesting_ = stop;
		}

		bool isFirstTestFailStopTesting() { return firstTestFailStopTesting_;}

		void incrementPerformedTestCount() { ++performedTestCount_; }
		
		void testFail(const std::string& message, 
			const std::string& testName, const std::string& testFile, 
			size_t testLine);

	private:
		std::vector<UnitTest*> tests_;
		std::ostream* outputStream_;
		bool firstTestFailStopTesting_;
		size_t performedTestCount_;
		size_t detectedFailCount_;

		UnitTester()
			: outputStream_(&std::cerr)
			, firstTestFailStopTesting_(false)
			, performedTestCount_(0)
			, detectedFailCount_(0) { }
		UnitTester(const UnitTester&);
		UnitTester& operator=(const UnitTester&);

		void errorMessage(const std::string& message, 
			const std::string& testName, const std::string& testFile, 
			size_t testLine);

		void testSummary();


	};

} // namespace jmlib

#endif
